package edu.suda.LoopCodePlus.service.impl;

import edu.suda.LoopCodePlus.entity.Problem;
import edu.suda.LoopCodePlus.service.ProblemService;
import edu.suda.LoopCodePlus.service.RunService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.*;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.rmi.RemoteException;
import java.util.concurrent.TimeUnit;

@Service
public class RunServiceImpl implements RunService {
    private static final String PYTHON_INTERPRETER = "python"; // 或者 "python3" 根据你的系统配置
    private static final long MAX_MEMORY_USAGE = 10 * 1024 * 1024; // 10 MB in bytes
    @Autowired
    private ProblemService problemService;
    @Override
    public File createTempPythonFile(String code) throws IOException{
        Path tempDirectory = Paths.get("E:\\temp");
        Path tempFile = Files.createTempFile(tempDirectory, "temp", ".py");

        try (PrintWriter writer = new PrintWriter(tempFile.toFile())) {
            writer.print(code);
        }

        return tempFile.toFile();
    }
    @Override
    public String runPythonCode(String code, Integer problemId) throws IOException, InterruptedException {
        // 根据问题ID查找对应的测试用例
        Problem problem = problemService.findProblemById(problemId);
        String cases = problem.getTestCase();
        System.out.println("测试用例如下");
        System.out.println(cases);
        //将cases中的null全部转换为None
        cases = cases.replace("null", "None");
        cases=cases.replace("true","True");
        cases=cases.replace("false","False");
        //代码的头部import
        String head="import io\n" +
                "import sys\n" +
                "import queue\n"+
                "import bisect\n" +
                "import time\n" +"import json\n"+
                "from bisect import bisect_left\n"+
                "from math import inf\n"+
                "from collections import defaultdict\n"+
                "import copy\n"+
                "from func_timeout import func_set_timeout, FunctionTimedOut\n";
        // 构建最终的Python代码字符串
        code = head+
                "cases="+cases+"\n"+
                "@func_set_timeout(5)\n" + // 设置函数超时时间为5秒
                code + "\n" + // 添加用户提供的代码
                "flg=0\n" +
                "for v in cases:\n" +
                "    sio = io.StringIO()\n" +
                "    sys.stdout = sio\n" +
                "    # 循环运行每一个测试用例\n" +
                "    try:\n" +
                "        c=main(*cases[v]['in'])\n" + // 调用main函数，并传入测试用例的输入参数
                "        if(c==cases[v]['out']):\n" +
                "            continue\n" +
                "        else:\n" +
                "            flg=1\n" +
                "            sys.stdout = sys.__stdout__  # 将标准输出复原\n" +
                "            sio.seek(0)\n" +
                "            print([cases[v], \"WA\", 4, bytes(sio.read(), encoding='utf-8').decode(),(int(v)-1)*100//len(cases)])\n" + // 输出错误信息
                "            break\n" +
                "    except FunctionTimedOut as e1:\n" +
                "        flg=1\n" +
                "        sys.stdout = sys.__stdout__  # 将标准输出复原\n" +
                "        sio.seek(0)\n" +
                "        print([cases[v], str(e1), 1, bytes(sio.read(), encoding='utf-8').decode(),(int(v)-1)*100//len(cases)])\n" + // 输出超时错误信息
                "        break\n" +
                "    except Exception as e2:\n" +
                "        flg=1\n" +
                "        sys.stdout = sys.__stdout__  # 将标准输出复原\n" +
                "        sio.seek(0)\n" +
                "        print([cases[v], str(e2), 2, bytes(sio.read(), encoding='utf-8').decode(),(int(v)-1)*100//len(cases)])\n" + // 输出其他异常信息
                "        break\n" +
                "sys.stdout = sys.__stdout__  # 将标准输出复原\n" +
                "sio.seek(0)\n" +
                "if(flg==0):\n" +
                "    print([{}, 'AC', 0, bytes(sio.read(), encoding='utf-8').decode(),100])"; // 如果所有测试用例都通过，则输出正确信息

        System.out.println("代码如下");
        System.out.println(code);

        // 创建临时Python文件，写入代码
        File tempFile = createTempPythonFile(code);

        // 创建ProcessBuilder来启动Python解释器
        ProcessBuilder processBuilder = new ProcessBuilder(PYTHON_INTERPRETER, tempFile.getAbsolutePath());
        Process process = processBuilder.start();

        // 内存限制
        MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
        MemoryUsage memoryUsage = memoryMXBean.getHeapMemoryUsage();

        // 记录进程开始前的内存使用情况
        long initialMemoryUsage = memoryUsage.getUsed();
        Thread.sleep(100); // 给一些时间让进程开始使用内存

        // 记录进程开始后的内存使用情况
        memoryUsage = memoryMXBean.getHeapMemoryUsage();
        long currentMemoryUsage = memoryUsage.getUsed();

        // 检查是否超出内存限制
        boolean isMemoryExceeded = (currentMemoryUsage - initialMemoryUsage) > MAX_MEMORY_USAGE;

        if (isMemoryExceeded) {
            process.destroy();
            throw new RuntimeException("Memory usage exceeded 10MB.");
        }

        // 读取进程的标准输出
        BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
        // 读取进程的错误输出
        BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));

        // 用来存储输出和错误输出的StringBuilder对象
        StringBuilder output = new StringBuilder();
        StringBuilder errorOutput = new StringBuilder();

        // 读取标准输出
        String line;
        while ((line = stdInput.readLine()) != null) {
            output.append(line).append(System.lineSeparator());
        }

        // 读取错误输出
        while ((line = stdError.readLine()) != null) {
            errorOutput.append(line).append(System.lineSeparator());
        }

        // 等待进程完成
        boolean isTimeout = false;
        try {
            if (!process.waitFor(5, TimeUnit.SECONDS)) { // 等待5秒
                isTimeout = true;
                process.destroy();
            }
        } catch (InterruptedException e) {
            process.destroy();
            Thread.currentThread().interrupt();
        }

        // 获取进程的退出码
        int exitCode = process.exitValue();

        // 只处理内存限制和编译错误
        if (isMemoryExceeded) {
            throw new RuntimeException("Memory usage exceeded 10MB.");
        } else if (exitCode != 0 && errorOutput.length() > 0) {
            throw new RuntimeException(errorOutput.toString());
        }
        // 如果一切正常，返回标准输出
        return output.toString();
    }
}